package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.DeleteVideoRequest;
import com.aliyuncs.vod.model.v20170321.DeleteVideoResponse;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.api.media.model.qo.QueryMediaModel;
import com.xuecheng.api.media.model.vo.MediaAuditVo;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.common.ResourceTypeEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.List;

@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {


    @Value("${aliyun.region}")
    private String region;
    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;


    //保存媒资信息
    @Transactional
    public MediaDTO saveMedia(MediaDTO mediaDTO) {

        //判断关键数据（file-id,filename,companyId）
        if(StringUtil.isBlank(mediaDTO.getFilename())||StringUtil.isBlank(mediaDTO.getFileId())){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //判断是否已经保存过该媒资信息
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getFileId,mediaDTO.getFileId());

        Media media = this.getOne(queryWrapper);

        if(!ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }

        //判断该媒资的类型（前端传来）
        if(ResourceTypeEnum.VIDEO.getCode().equals(mediaDTO.getType())){

            //如果是视频，获取视频的播放地址
            GetPlayInfoResponse response = null;
            try {
                //初始化vod客户端
                DefaultAcsClient vodClient = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

                //创建请求
                response = AliyunVODUtil.getPlayInfo(vodClient, mediaDTO.getFileId());
            } catch (Exception e) {
                log.error("阿里云VOD出错啦，{}",e.getMessage());

                ExceptionCast.cast(MediaErrorCode.E_140012);
            }

            //解析请求得到播放地址，默认获取第一个播放地址
            List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();

            GetPlayInfoResponse.PlayInfo playInfo = playInfoList.get(0);

            String playURL = playInfo.getPlayURL();

            //将播放地址赋值
            mediaDTO.setUrl(playURL);

        }

        //保存媒资
        Media dto2po = MediaConvert.INSTANCE.dto2po(mediaDTO);

        boolean save = this.save(dto2po);

        //判断是否保存成功
        if(!save){
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }

        LambdaQueryWrapper<Media> queryWrapper1 = new LambdaQueryWrapper<>();

        queryWrapper1.eq(Media::getFileId,mediaDTO.getFileId());

        Media media1 = this.getOne(queryWrapper1);

        MediaDTO po2dto = MediaConvert.INSTANCE.po2dto(media1);

        return po2dto;
    }


    //分页查询媒资信息
    public PageVO queryMediaList(PageRequestParams params, QueryMediaModel model,Long companyId) {

        //判断分页数据是否合法
        if(params.getPageNo()<1){
            //默认值
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }

        if(params.getPageSize()<1){
            //默认值
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        //构造查询条件
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();

        //文档类型
        queryWrapper.eq(!StringUtil.isBlank(model.getType()),Media::getType,model.getType());

        //文档名称
        queryWrapper.like(!StringUtil.isBlank(model.getFilename()),Media::getFilename,model.getFilename());

        //文档属于的公司(有公司id就是机构查询)
        queryWrapper.eq(!ObjectUtils.isEmpty(companyId),Media::getCompanyId,companyId);

        //构造分页查询参数
        Page<Media> page = new Page<>(params.getPageNo(),params.getPageSize());

        //调用MP分页查询方法
        Page<Media> mediaPage = this.page(page, queryWrapper);

        //获取数据的总条数
        long total = mediaPage.getTotal();

        //获取数据结果集
        List<Media> records = mediaPage.getRecords();

        //创建一个空集合
        List<MediaDTO> dtoList = Collections.emptyList();

        //将po对象转为dto对象
        if(!CollectionUtils.isEmpty(records)){
            dtoList =MediaConvert.INSTANCE.pos2dtos(records);
        }

        //封装到PageVo对象
        PageVO pageVO = new PageVO(dtoList,total,params.getPageNo(),params.getPageSize());

        //返回
        return pageVO;
    }


    //预览媒资
    public String previewMedia(Long mediaId, Long companyId) {
        //判断关键数据
        if(ObjectUtils.isEmpty(mediaId)){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //判断该媒资信息是否存在
        Media media = this.getById(mediaId);

        if(ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        //判断媒资是否被删除
        if(CommonEnum.DELETE_FLAG.getCode().equals(media.getStatus())){
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }

        //判断是否是同一家公司
        if(!ObjectUtils.nullSafeEquals(companyId,media.getCompanyId())){
            ExceptionCast.cast(CommonErrorCode.E_403000);
        }

        //获取媒资url
        String playURL = null;
        try {
            //初始化vod客户端
            DefaultAcsClient vodClient = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

            //发送请求
            GetPlayInfoResponse response = AliyunVODUtil.getPlayInfo(vodClient, media.getFileId());

            //解析请求
            List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();

            GetPlayInfoResponse.PlayInfo playInfo = playInfoList.get(0);

            playURL = playInfo.getPlayURL();
        } catch (Exception e) {
            log.error("阿里云VOD出错啦，{}",e.getMessage());

            ExceptionCast.cast(MediaErrorCode.E_140012);
        }

        return playURL;
    }

    //预览媒资
    public String RunPreviewMedia(Long mediaId) {
        //判断关键数据
        if(ObjectUtils.isEmpty(mediaId)){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //判断该媒资信息是否存在
        Media media = this.getById(mediaId);

        if(ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        //判断媒资是否被删除
        if(CommonEnum.DELETE_FLAG.getCode().equals(media.getStatus())){
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }

        //获取媒资url
        String playURL = null;
        try {
            //初始化vod客户端
            DefaultAcsClient vodClient = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

            //发送请求
            GetPlayInfoResponse response = AliyunVODUtil.getPlayInfo(vodClient, media.getFileId());

            //解析请求
            List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();

            GetPlayInfoResponse.PlayInfo playInfo = playInfoList.get(0);

            playURL = playInfo.getPlayURL();
        } catch (Exception e) {
            log.error("阿里云VOD出错啦，{}",e.getMessage());

            ExceptionCast.cast(MediaErrorCode.E_140012);
        }

        return playURL;
    }



    //删除媒资
    @Transactional
    public void deleteMedia(Long mediaId, Long companyId) {

        //判断关键数据
        if(ObjectUtils.isEmpty(mediaId) || ObjectUtils.isEmpty(companyId)){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //判断该媒资是否存在
        Media media = this.getById(mediaId);

        if(ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        String fileId = media.getFileId();

/*        //判断媒资是否是删除态
        if(CommonEnum.DELETE_FLAG.getCode().equals(media.getStatus())){
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }

        //构造修改条件
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.eq(Media::getId,mediaId);

        //改为删除态
        updateWrapper.set(Media::getStatus,CommonEnum.DELETE_FLAG.getCode());

        boolean update = this.update(updateWrapper);

        //判断是否成功
        if(!update){
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }*/

        //删除
        boolean remove = this.removeById(mediaId);

        if(!remove){
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }

        //删除阿里云中的视频

        try {
            //初始化vod客户端
            DefaultAcsClient vodClient = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

            DeleteVideoResponse response = new DeleteVideoResponse();

            response = deleteVideo(vodClient,fileId);

            if(ObjectUtils.isEmpty(response)){
                ExceptionCast.cast(MediaErrorCode.E_140009);
            }


            System.out.println("response = " + response.getRequestId());
        } catch (Exception e) {
            log.error("阿里云VOD出错啦，{}",e.getMessage());

            ExceptionCast.cast(MediaErrorCode.E_140012);
        }

    }


    public static DeleteVideoResponse deleteVideo(DefaultAcsClient client,String fileId) throws Exception {
        DeleteVideoRequest request = new DeleteVideoRequest();

        //支持传入多个视频ID，多个用逗号分隔
        request.setVideoIds(fileId);
        return client.getAcsResponse(request);
    }


    //根据id查询媒资信息
    public RestResponse<MediaDTO> queryMediaById(Long mediaId) {

        //判断关键数据
        if(ObjectUtils.isEmpty(mediaId)){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        Media media = this.getById(mediaId);

        //判断媒资信息是否存在
        if(ObjectUtils.isEmpty(media)){
            return RestResponse.validfail(MediaErrorCode.E_140005);
        }

        //判断媒资的审核状态
        if(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(media.getAuditStatus()) ||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(media.getAuditStatus()) ||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(media.getAuditStatus())){

            return RestResponse.validfail(MediaErrorCode.E_140010);
        }

        //判断媒资是否是删除态
        if(CommonEnum.DELETE_FLAG.getCode().equals(media.getStatus())){
            return RestResponse.validfail(MediaErrorCode.E_140005);
        }

        MediaDTO mediaDTO = MediaConvert.INSTANCE.po2dto(media);

        return RestResponse.success(mediaDTO);
    }


    //运营平台审核媒资信息
    @Transactional
    public void modifyMediaAudit(MediaAuditVo mediaAuditVo) {

        //判断关键数据
        if(ObjectUtils.isEmpty(mediaAuditVo.getId()) || StringUtil.isBlank(mediaAuditVo.getAuditStatus())){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //运营平台只能修改为两种状态（审核通过、审核未通过）
        if(!AuditEnum.AUDIT_PASTED_STATUS.getCode().equals(mediaAuditVo.getAuditStatus()) ||
            !AuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(mediaAuditVo.getAuditStatus())){
            ExceptionCast.cast(MediaErrorCode.E_140015);
        }

        //查询此媒资信息是否存在
        Media media = this.getById(mediaAuditVo.getId());

        if(ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        //判断媒资是否提交，只能审核已提交的媒资
        if(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(media.getAuditStatus())){
            ExceptionCast.cast(MediaErrorCode.E_140016);
        }

        //修改媒资审核状态
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();

        //根据媒资id
        updateWrapper.eq(Media::getId,mediaAuditVo.getId());

        //审核意见
        updateWrapper.set(!ObjectUtils.isEmpty(mediaAuditVo.getAuditMind()),Media::getAuditMind,mediaAuditVo.getAuditMind());

        //审核状态
        updateWrapper.set(Media::getAuditStatus,mediaAuditVo.getAuditStatus());

        boolean update = this.update(updateWrapper);

        //判断是否修改成功
        if(!update){
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }
    }
}
